package com.video.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.video.constants.SysConstants;
import com.video.dao.TagUserMapper;
import com.video.dao.TagsMapper;
import com.video.dao.UsersMapper;
import com.video.entity.LoginUser;
import com.video.entity.TagUser;
import com.video.entity.Tags;
import com.video.entity.User;
import com.video.exception.SystemException;
import com.video.exception.VideoException;
import com.video.form.LoginForm;
import com.video.result.AppHttpCodeEnum;
import com.video.result.ResultVO;
import com.video.service.UsersService;
import com.video.utils.BeanCopyUtils;
import com.video.utils.JwtUtil;
import com.video.utils.MobileUtil;
import com.video.utils.RedisCache;
import com.video.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * (User)表服务实现类
 *
 * @author baoshuai
 * @since 2022-12-14 21:02:16
 */
@Service("usersService")
public class UsersServiceImpl extends ServiceImpl<UsersMapper, User> implements UsersService {

    public static final String USER_DEFAULT_IMG = "img/default.png";

    @Resource
    private TagUserMapper tagUserMapper;

    @Resource
    private TagsMapper tagsMapper;

    @Resource
    private RedisCache redisCache;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVO modifyUserInfo(UpdateUserInfoVo updateUserInfoVo) {
        User user = getById(updateUserInfoVo.getId());
        if (Objects.isNull(user)) {
            throw new VideoException(AppHttpCodeEnum.USER_NOT_EXIST);
        }
        user = BeanCopyUtils.copyBean(updateUserInfoVo, User.class);
        //修改用户基本信息
        updateById(user);

        //修改用户标签信息
        modifyUserTag(updateUserInfoVo.getUpdateUserTagVo());

        return ResultVO.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVO register(RegisterVo registerVo) {
        if (!StringUtils.hasText(registerVo.getMobile())) {
            throw new VideoException(AppHttpCodeEnum.MOBILE_NOT_NULL);
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getMobile, registerVo.getMobile());
        User user = getOne(queryWrapper);
        if (!Objects.isNull(user)) {
            throw new VideoException(AppHttpCodeEnum.USER_ALREADY_EXIST);
        }

        String foxId = String.valueOf(System.currentTimeMillis());

        user = User.builder()
                .mobile(registerVo.getMobile())
                .foxId(foxId)
                .nickname(foxId)
                .userImg(USER_DEFAULT_IMG).build();

        //保存用户信息
        save(user);

        //保存用户选择的标签
        List<Long> selectTags = registerVo.getSelectTags();
        for (Long tagId : selectTags) {
            TagUser tagUser = new TagUser().setUserId(user.getId()).setTagId(tagId);
            tagUserMapper.insert(tagUser);
        }

        //保存用户自定义标签
        saveUserCustomTags(registerVo.getCustomTags(), user.getId());

        return ResultVO.success();
    }

    @Override
    public ResultVO getUserTag(Long userId) {
        if (isUserExist(userId)) {
            throw new VideoException(AppHttpCodeEnum.USER_NOT_EXIST);
        }

        // 获取用户的标签
        LambdaQueryWrapper<TagUser> tagUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tagUserLambdaQueryWrapper.eq(TagUser::getUserId, userId);
        List<TagUser> tagUserList = tagUserMapper.selectList(tagUserLambdaQueryWrapper);
        //判断用户是否有标签
        if (tagUserList.size() == 0) {
            return ResultVO.success(new ArrayList<>());
        }

        //获取用户的标签id
        List<Long> tagIds = tagUserList.stream()
                .map(TagUser::getTagId).collect(Collectors.toList());

        List<Tags> tagsList = tagsMapper.selectBatchIds(tagIds);

        List<UserTagVo> userTagVoList = tagsList.stream()
                .map(tag -> new UserTagVo(tag.getId(), tag.getTag()))
                .collect(Collectors.toList());

        return ResultVO.success(userTagVoList);
    }

    @Override
    public ResultVO modifyUserTag(UpdateUserTagVo updateUserTagVo) {
        Long userId = updateUserTagVo.getUserId();
        if (isUserExist(userId)) {
            throw new VideoException(AppHttpCodeEnum.USER_NOT_EXIST);
        }
        //删除原有的标签
        LambdaQueryWrapper<TagUser> tagUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tagUserLambdaQueryWrapper.eq(TagUser::getUserId, userId);
        tagUserMapper.delete(tagUserLambdaQueryWrapper);

        //添加选择的标签
        List<Long> selectTags = updateUserTagVo.getSelectTags();
        for (Long selectTagId : selectTags) {
            TagUser tagUser = new TagUser().setTagId(selectTagId).setUserId(userId);
            tagUserMapper.insert(tagUser);
        }

        //添加自定义的标签
        saveUserCustomTags(updateUserTagVo.getCustomTags(), updateUserTagVo.getUserId());
        return ResultVO.success();
    }

    @Override
    public ResultVO getUserInfo(Long userId) {
        //查询用户
        User user = getById(userId);
        if (Objects.isNull(user)) {
            throw new VideoException(AppHttpCodeEnum.USER_NOT_EXIST);
        }
        UserVo userVo = BeanCopyUtils.copyBean(user, UserVo.class);
        //查询用户标签
        LambdaQueryWrapper<TagUser> tagUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tagUserLambdaQueryWrapper.eq(TagUser::getUserId, userId);
        List<TagUser> tagUserList = tagUserMapper.selectList(tagUserLambdaQueryWrapper);

        List<Tags> tagsList = new ArrayList<>();
        for (TagUser tagUser : tagUserList) {
            LambdaQueryWrapper<Tags> tagsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            tagsLambdaQueryWrapper.eq(Tags::getId, tagUser.getTagId());
            Tags tag = tagsMapper.selectOne(tagsLambdaQueryWrapper);
            tagsList.add(tag);
        }
        userVo.setTags(tagsList);

        return ResultVO.success(userVo);
    }

    @Override
    public ResultVO login(LoginForm loginForm) {
        String mobile = loginForm.getMobile();
        if (mobile.length() != 11) {
            throw new SystemException(AppHttpCodeEnum.MOBILE_ERROR);
        }
        if (!MobileUtil.checkIsNumber(mobile)) {
            throw new SystemException(AppHttpCodeEnum.MOBILE_ERROR);
        }

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getMobile, mobile);
        User user = getOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new SystemException(AppHttpCodeEnum.USER_NOT_EXIST);
        }
        String token = JwtUtil.createJWT(user.getId().toString());
        LoginUser loginUser = new LoginUser(user, token);
        redisCache.setCacheObject(SysConstants.USER_LOGIN + user.getId(), loginUser, 1, TimeUnit.HOURS);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("userInfo", user);
        return ResultVO.success(AppHttpCodeEnum.LOGIN_SUCCESS, map);
    }

    private void saveUserCustomTags(List<String> customTags, Long userId) {
        // 查询所有标签
        List<String> tagNameList = tagsMapper.selectList(null).stream()
                .map(Tags::getTag).collect(Collectors.toList());

        // 遍历用户自定义标签
        for (String customTag : customTags) {
            TagUser tagUser = new TagUser().setUserId(userId);
            if (!tagNameList.contains(customTag)) {
                //自定义标签不存在，保存标签
                Tags tags = new Tags().setTag(customTag).setTodayCounts(0).setTotalCounts(0);
                tagsMapper.insert(tags);

                tagUser.setTagId(tags.getId());
            } else {
                //存在自定义标签，直接保存用户标签表
                LambdaQueryWrapper<Tags> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Tags::getTag, customTag);
                //获取标签id
                Tags tag = tagsMapper.selectOne(wrapper);

                tagUser.setTagId(tag.getId());
            }
            //保存用户标签表
            tagUserMapper.insert(tagUser);
        }
    }

    private boolean isUserExist(Long userId) {
        User user = getById(userId);
        return Objects.isNull(user);
    }

}